/* License Notice:
 *
 * This program is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 * This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *   GNU General Public License for more details.
 * You should have received a copy of the GNU General Public License
 *   along with this program. If not, see <https://www.gnu.org/licenses/>.
 */

/**
 * @file main.cpp
 * @author TooOld2Rock'nRoll
 */
/*---- Includes ----*/
#include <memory>
#include <glm/fwd.hpp>

#include "arcade_fighter.hpp"

#include "demo_character.hpp"
#include "demo_level.hpp"

#include "graphics/font.hpp"


/*---- Global Variables ----*/
ResourceManager *resource_manager = nullptr;


/*---- Function Prototypes ----*/


/*---- Implementation ----*/
int main (int argc, char *argv[])
{
    int ERROR = 0;
    int i = 0;

    /*** must be initialized before all other OpenGl objects ***/
    ArcadeFighter game("Arcade Fighter Demo :D", 1, (SDL_WindowFlags)(SDL_WINDOW_RESIZABLE | SDL_WINDOW_MAXIMIZED | SDL_WINDOW_ALLOW_HIGHDPI));

    Shader *s_basic = nullptr;

    DomainID_t player_dom_id[2] = {0, 0};
    Player *player_one = nullptr;
    Player *player_two = nullptr;
    DemoCharacter *puppet[2] = {nullptr, nullptr};
    std::shared_ptr<glm::vec4> player_two_color = std::make_shared<glm::vec4>(0.f, 0.f, 2.5, 1.f);

    DemoLevel *demo_level = nullptr;


    resource_manager = &ResourceManager::instance ();
    s_basic = resource_manager->getBasicShader (ResourceManager::global_domain_id);

    demo_level = new DemoLevel ();

    //player one
    player_one = new Player ();
    //we could use de global id, but players may change their content mid game, easier to clean and recreate.
    player_dom_id[0] = resource_manager->createNewDomain ();

    //directional
    player_one->mapInput (controller_button_map_t::DPAD_RIGHT, SDL_SCANCODE_D);
    player_one->mapInput (controller_button_map_t::DPAD_LEFT, SDL_SCANCODE_A);
    player_one->mapInput (controller_button_map_t::DPAD_UP, SDL_SCANCODE_W);
    player_one->mapInput (controller_button_map_t::DPAD_DOWN, SDL_SCANCODE_S);

    //action
    player_one->mapInput (controller_button_map_t::ACTION_A, SDL_SCANCODE_U);
    player_one->mapInput (controller_button_map_t::ACTION_B, SDL_SCANCODE_I);
    player_one->mapInput (controller_button_map_t::ACTION_X, SDL_SCANCODE_O);
    player_one->mapInput (controller_button_map_t::ACTION_Y, SDL_SCANCODE_P);

    //Player1 Character will be a custom implementation
    puppet[0] = new DemoCharacter (player_dom_id[0], s_basic);
    puppet[0]->load ();
    player_one->setCharacter (puppet[0]); ///@todo test what happens to remove a puppet or a player, what should be the correct behavior???

    game.setPlayer (0, player_one);
    demo_level->addPlayableCharacter (0, puppet[0]);


    //player two
    player_two = new Player ();
    //we could use de global id, but players may change their content mid game, easier to clean and recreate.
    player_dom_id[1] = resource_manager->createNewDomain ();

    player_two->mapInput (controller_button_map_t::DPAD_RIGHT, SDL_SCANCODE_RIGHT);
    player_two->mapInput (controller_button_map_t::DPAD_LEFT, SDL_SCANCODE_LEFT);
    player_two->mapInput (controller_button_map_t::DPAD_UP, SDL_SCANCODE_UP);
    player_two->mapInput (controller_button_map_t::DPAD_DOWN, SDL_SCANCODE_DOWN);

    //action
    player_two->mapInput (controller_button_map_t::ACTION_A, SDL_SCANCODE_M);
    player_two->mapInput (controller_button_map_t::ACTION_B, SDL_SCANCODE_COMMA);
    player_two->mapInput (controller_button_map_t::ACTION_X, SDL_SCANCODE_PERIOD);
    player_two->mapInput (controller_button_map_t::ACTION_Y, SDL_SCANCODE_SLASH);

    //Player2 Character will be the default implementation
    puppet[1] = new DemoCharacter (player_dom_id[1], s_basic);
    puppet[1]->load ();

    for (i = puppet[1]->getSpriteCount (); i--; )
        puppet[1]->getSprite(i).getColorTint().entangle (player_two_color);

    player_two->setCharacter (puppet[1]);

    game.setPlayer (1, player_two);
    demo_level->addPlayableCharacter (1, puppet[1]);

    //main loop, will run until ESC or close is pressed
    while (!game.shouldQuit ())
    {
        game.levelStart (*demo_level);
    }//end while (!should_quit)

    delete (demo_level);
    delete (player_one);
    delete (player_two);
    delete (puppet[0]);
    delete (puppet[1]);

    return ERROR;
}//END main ()

